package com.andnnl.bitmap;

import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.util.RandomUtil;
import org.roaringbitmap.RoaringBitmap;
import org.roaringbitmap.longlong.Roaring64Bitmap;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 是bitmap的优化版，会根据插入的元素动态调整内存，不会出现因为数据少而占用大量内存的情况，并会做适当的压缩
 *
 * 数据结构及原理
 * Roaring64Bitmap方法依赖于ART数据结构来保存键/值对。Key由最高48位元素组成，而值是16位Roaring容器
 * LongUtils类会将64位的长整形（long）拆分成高48位和低16位两部分来处理。
 *
 * Created by chenss on 2021/4/28.
 */
public class HashMapTest {
    static long maxMobile=20000000000L;//100亿
    static long minMobile=10000000000L;//100亿
    public static void main(String[] args) throws IOException {
//        test1();
//        System.in.read();
         testLong();
         System.in.read();
    }

    private static void testLong() {
        TimeInterval timer=new TimeInterval();
        Map<Long,Object> map=new HashMap<>();
        Object obj=new Object();
        for (int i = 0; i < 10000*2000; i++) {
            long v = RandomUtil.randomLong(maxMobile / 10, maxMobile);
//            long v = RandomUtil.randomLong(minMobile, maxMobile);
//            rb.add(v);
            map.put(v,obj);
        }
        System.out.println("add finish times:"+timer.intervalRestart());
        System.out.println("size times:"+timer.intervalRestart()+" map.size()"+map.size());
        AtomicInteger size = new AtomicInteger();
        map.forEach((k,v)->{
//            System.out.println(v);
            size.getAndIncrement();
        });
//        LongIterator it = rb.getLongIterator();
//        while (it.hasNext()) {
////            System.out.println(it.next());
//            size++;
//        }
        System.out.println(size+" times:"+timer.intervalRestart());

         map.clear();
    }

    private static void test1() {
        RoaringBitmap rr = RoaringBitmap.bitmapOf(1, 2, 3, 1000);
        RoaringBitmap rr2 = new RoaringBitmap();
        rr2.add(4000L, 4255L);
        // 返回存储在这个位图中的第j个值。
        // 提供的值需要比基数小，否则抛出IllegalArgumentException异常。
        // 最小的值在索引0处。注意，这个函数与rank函数的约定不同，后者在对最小值排序时返回1。
        // would return the third value or 1000
        rr.select(3);
        // Rank返回小于或等于x的整数的数目(Rank(∞)是GetCardinality())。
        // 如果将最小的值作为参数提供，则该函数将返回1。
        // 如果提供的值小于最小值，则返回0。
        // would return the rank of 2, which is index 1
        rr.rank(2);
        // will return true
        rr.contains(1000);
        // will return false
        rr.contains(7);
        // 并集
        // new bitmap
        RoaringBitmap rror = RoaringBitmap.or(rr, rr2);
        //
        //in-place computation
        rr.or(rr2);
        // true
        boolean equals = rror.equals(rr);
        if (!equals) {
            throw new RuntimeException("bug");
        }
        // number of values stored?
        long cardinality = rr.getLongCardinality();
        System.out.println(cardinality);
        long size = 0 ;
        // a "forEach" is faster than this loop, but a loop is possible:
        for (int i : rr) {
            System.out.println(i);
            size++;
        }
        // 259
        System.out.println(size);
    }
}
